package com.dome.gateway.filter;

import com.alibaba.fastjson.JSON;
import com.dome.auth.utils.JwtUtils;
import com.dome.client.config.result.RtnResultVO;
import com.dome.gateway.config.ZuulAuthApiConfiguration;
import com.dome.redis.utils.JedisUtils;
import com.dome.util.constans.CommonConstants;
import com.dome.util.constans.RedisKeyConstants;
import com.google.common.net.HttpHeaders;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_DECORATION_FILTER_ORDER;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;

/**
 * zuul过滤器
 */
@Component
@Slf4j
public class BaseZuulFilter extends ZuulFilter {

    @Autowired
    private ZuulAuthApiConfiguration zuulAuthApiConfiguration;
//    @Autowired
//    private StringRedisTemplate stringRedisTemplate;
    /**
     * pre：可以在请求被路由之前调用
     * route：在路由请求时候被调用
     * post：在route和error过滤器之后被调用
     * error：处理请求时发生错误时被调用
     * @return
     */
    @Override
    public String filterType() {
        return PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return PRE_DECORATION_FILTER_ORDER - 1;
    }

    @Override
    public boolean shouldFilter() {
        // 表示是否需要执行该filter，true表示执行，false表示不执行
        HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
        try {
            List<String> targetUrls=zuulAuthApiConfiguration.getIgnoreUrls();
            String uri= request.getRequestURI();
            if (!isMatchAuthorizeUrl(targetUrls,uri)){
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return true;
        }
        RequestContext ctx = RequestContext.getCurrentContext();
        //将jwt token中的用户信息传给服务 传递给后续微服务
        ctx.addZuulRequestHeader(CommonConstants.X_CLIENT_TOKEN, zuulAuthApiConfiguration.getSigningKey());
        return false;
    }

    /**
     * 是否匹配到允许自动鉴权url地址
     * @param patternUrl
     * @param url
     * @return
     */
    private boolean isMatchAuthorizeUrl(List<String> patternUrl, String url){
        if (patternUrl==null||patternUrl.size()==0){
            return false;
        }
        AntPathMatcher pathMatcher=new AntPathMatcher();
        for (String pattern:patternUrl){
            if (pathMatcher.match(pattern.trim(),url)){
                return true;
            }
        }
        return false;
    }

    @Override
    public Object run() throws ZuulException {
        // filter需要执行的具体操作
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        String authentication = request.getHeader(HttpHeaders.AUTHORIZATION);
        //String domain = request.getHeader(RedisKeyConstants.DOMAIN);

        if(StringUtils.isEmpty(authentication)) {
            RtnResultVO result = new RtnResultVO();
            result.setCode(HttpStatus.SC_GONE);
            result.setMsg("表头鉴权信息不能为空");
            String json = JSON.toJSONString(result);
            ctx.setResponseBody(json);
            ctx.getResponse().setHeader("content-type", MediaType.APPLICATION_JSON_UTF8_VALUE);
            ctx.getResponse().setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
            // 过滤该请求，不对其进行路由
            ctx.setSendZuulResponse(false);
            return false;
        }
//        String account = CookieUtil.getValueByName("account", request);
        String account = JwtUtils.loginRedisKey(authentication);
        if(StringUtils.isNotBlank(account)) {
            if(JedisUtils.exists(account)) {
                JedisUtils.expire(account, RedisKeyConstants.COOKIE_TIMEOUT);
                //将jwt token中的用户信息传给服务 传递给后续微服务
                ctx.addZuulRequestHeader(CommonConstants.X_CLIENT_TOKEN, authentication);
//                if(StringUtils.isBlank(domain)) {
//                    ctx.addZuulRequestHeader(RedisKeyConstants.DOMAIN, domain);
//                }
                log.debug("zuul resend redis ok {} ",CommonConstants.X_CLIENT_TOKEN,authentication);
                return false;
            }
        }


        ctx.getResponse().setHeader("content-type", MediaType.APPLICATION_JSON_UTF8_VALUE);
        ctx.getResponse().setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
//        ctx.setSendZuulResponse(false);
//        ctx.setResponseStatusCode(401);
        RtnResultVO result = new RtnResultVO();
        result.setCode(HttpStatus.SC_GONE);
        result.setMsg("鉴权失败.登陆超时");
        String json = JSON.toJSONString(result);
        ctx.setResponseBody(json);
        // 过滤该请求，不对其进行路由
        ctx.setSendZuulResponse(false);
        return null;
    }
}